package com.miyake.dsp.osa.ui;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import com.miyake.dsp.osa.AnalysisProperty;

public abstract class AnalysisSettingUI extends JFrame {
	private static final String FORMULA_5TH = "y=x(1)+x(2)*t+x(3)*t^2+x(4)*t^3+x(5)*t^4+x(6)*t^5";
	private static final String FORMULA_4TH = "y=x(1)+x(2)*t+x(3)*t^2+x(4)*t^3+x(5)*t^4";
	private static final String FORMULA_3RD = "y=x(1)+x(2)*t+x(3)*t^2+x(4)*t^3";
	private static final String FORMULA_2ND = "y=x(1)+x(2)*t+x(3)*t^2";
	private static final String FORMULA_LINEAR = "y=x(1)+x(2)*t";
	/**
	 * 
	 */
	private static final long serialVersionUID = -3069574507446252689L;
	private static int WIDGET_HEIGH = 24;
	public abstract void onSetClick(AnalysisProperty prop);
	
	public AnalysisSettingUI(AnalysisProperty prop) throws HeadlessException {
		super();
		initialize(prop);
	}
	
	
	private JTextField fittingSpan;
	private JTextField maskedSpan;
	private JTextField bpfBandwidthText;
	private JTextField bpfLevelText;
	private JTextField thresholdText;
	private JTextField rbwText;
	private JCheckBox fittingVisible;
	private JCheckBox maskedVisible;
	private JCheckBox fitInLogCheck;
	private JTextField formula;
	private JComboBox combo;
	private JComboBox methodCombo;
	private JComboBox rbwCombo;
	private JComboBox nfCombo;
	private JRadioButton pointRadio;
	private JRadioButton areaRadio;
	private JRadioButton realSpanRadio;
	private JRadioButton pointSpanRadio;
	//private JRadioButton centerRadio;
	private JComboBox spanCombo;
	private JRadioButton manualRadio;
	private JTextField nfCalText;
	private JTextField poutText;
	private JTextField pinText;
	private JLabel fittingUnit = new JLabel();
	private JLabel maskedUnit = new JLabel();
	private JTextField sliceText;
	private JCheckBox checkLogAxis;
	private JRadioButton thresholdRadio;
	private JRadioButton peakRadio;
	private JTextField cutlevelText;
	
	private void initialize(AnalysisProperty prop) {
		this.setTitle("Fitting Setting");
		this.setSize(new Dimension(600, 460));
		Container c = this.getContentPane();
		c.setLayout(new FlowLayout());
		c.add(createMethod(prop.getMethod()));
		c.add(createLogAxis(prop.isLog()));
		JPanel fittingPanel = new JPanel();
		fittingPanel.setLayout(new FlowLayout());
		fittingPanel.setPreferredSize(new Dimension(590, 240));
		fittingPanel.setBorder(new TitledBorder("Fitting"));
		fittingPanel.add(createAutoSpan(prop.getSpanMethod()));
		fittingPanel.add(createPoint(prop.isPoint()));
		
		fittingPanel.add(createMarkerVisible(prop.isFittingVisible(), prop.isMaskedVisible()));

		fittingPanel.add(createSpanMethod(prop.isRealSpan()));
		fittingPanel.add(createFittingSpan(prop.getFittingSpan()));
		fittingPanel.add(createMaskedSpan(prop.getMaskedSpan()));
		
		fittingPanel.add(createFitIntLog(prop.isFitInLog()));
		fittingPanel.add(createFormula(prop.getFormula()));
		
		c.add(fittingPanel);
		
		c.add(createRbw(prop.getRbw(), prop.getRbwValue()));
		c.add(createNF(prop.getNfcalc()));
		c.add(createNFCal(prop.getK()));
		c.add(createPinLoss(prop.getPinLos()));
		c.add(createPoutLoss(prop.getPoutLoss()));
		c.add(createBpfLevel(prop.getBpfLevel()));
		c.add(createBpfBandwidth(prop.getBpfBandwidth()));
		c.add(createSliceLevel(prop.getSliceLevel()));
		c.add(createThreshold(prop.getPeakThreshold()));
		c.add(createChannelType(prop.isPeak(), prop.getCutLevel()));
		c.add(createSetButton());

	}


	private Component createChannelType(boolean peak, double cutLevel) {
		JPanel p = new JPanel();
		p.setBorder(new TitledBorder("Channel Definition"));
		peakRadio = new JRadioButton("Peak");
		thresholdRadio = new JRadioButton("Threshold");
		peakRadio.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				thresholdRadio.setSelected(!peakRadio.isSelected());
				updateCutLevelText();
			}
		});
		thresholdRadio.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				peakRadio.setSelected(!thresholdRadio.isSelected());
				updateCutLevelText();
			}
		});
		cutlevelText = new JTextField();
		cutlevelText.setText(String.valueOf(cutLevel));
		cutlevelText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		p.add(peakRadio);
		p.add(thresholdRadio);
		p.add(new JLabel("Cut Level"));
		p.add(cutlevelText);
		
		peakRadio.setSelected(peak);
		thresholdRadio.setSelected(!peak);
		
		updateCutLevelText();
		return p;
	}

	private void updateCutLevelText() {
		if (thresholdRadio.isSelected()) {
			cutlevelText.setEnabled(true);
		}
		else {
			cutlevelText.setEnabled(false);
		}
	}

	private Component createLogAxis(boolean log) {
		checkLogAxis = new JCheckBox("Log Axis");
		checkLogAxis.setSelected(log);
		return checkLogAxis;
	}

	private Component createSliceLevel(double sliceLevel) {
		JPanel p = new JPanel();
		p.add(new JLabel("Slice Level"));
		sliceText = new JTextField();
		sliceText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		sliceText.setText(String.valueOf(sliceLevel));
		p.add(sliceText);
		return p;
	}

	private Component createPoutLoss(double poutLoss) {
		JPanel p = new JPanel();
		p.add(new JLabel("Pout Loss"));
		poutText = new JTextField();
		poutText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		poutText.setText(String.valueOf(poutLoss));
		p.add(poutText);
		return p;
	}

	private Component createPinLoss(double pinLoss) {
		JPanel p = new JPanel();
		p.add(new JLabel("Pin Loss"));
		pinText = new JTextField();
		pinText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		pinText.setText(String.valueOf(pinLoss));
		p.add(pinText);
		return p;
	}

	private Component createNFCal(double k) {
		JPanel p = new JPanel();
		p.add(new JLabel("NF Cal"));
		nfCalText = new JTextField();
		nfCalText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		nfCalText.setText(String.valueOf(k));
		p.add(nfCalText);
		return p;
	}

	private Component createMarkerVisible(boolean fittingVisible2,
			boolean maskedVisible2) {
		
		JPanel p = new JPanel();
		p.setBorder(new TitledBorder("Marker Visible"));
		
		fittingVisible = new JCheckBox("Fitting Marker");
		fittingVisible.setSelected(fittingVisible2);
		maskedVisible = new JCheckBox("Masked Marker");
		maskedVisible.setSelected(maskedVisible2);
		p.add(fittingVisible);
		p.add(maskedVisible);
		return p;
	}

	private Component createAutoSpan(String method) {
		JPanel p = new JPanel();
		p.setBorder(new TitledBorder("Span "));
		spanCombo = new JComboBox();
		p.add(spanCombo);
		
		spanCombo.addItem("Center");
		spanCombo.addItem("Res");
		spanCombo.addItem("Manual");
		
		spanCombo.setSelectedItem(method);
		
		spanCombo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				updateFittingSpan();
			}
		});
				
		updateFittingSpan();
		return p;
	}

	private void updateFittingSpan() {
		if (fittingSpan == null)
			return;
		
		if (spanCombo.getSelectedItem().equals("Center")) {
			fittingSpan.setEnabled(false);
		}
		else {
			fittingSpan.setEnabled(true);
		}
	}

	private Component createSpanMethod(boolean realSpan) {
		JPanel p = new JPanel();
		p.setBorder(new TitledBorder("Span Method"));
		realSpanRadio = new JRadioButton("Real Value");
		realSpanRadio.setSelected(realSpan);
		p.add(realSpanRadio);
		realSpanRadio.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				pointSpanRadio.setSelected(!realSpanRadio.isSelected());
				updateSpanUnit();
			}
			
		});
		pointSpanRadio = new JRadioButton("Point");
		pointSpanRadio.setSelected(!realSpan);
		p.add(pointSpanRadio);
		pointSpanRadio.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				realSpanRadio.setSelected(!pointSpanRadio.isSelected());
				updateSpanUnit();
			}
		});
		
		updateSpanUnit();
		return p;
	}

	private void updateSpanUnit() {
		if (pointSpanRadio.isSelected()) {
			fittingUnit.setText("pt");
			maskedUnit.setText("pt");
		}
		else {
			fittingUnit.setText("nm");
			maskedUnit.setText("nm");
		}
	}

	private Component createThreshold(double peakThreshold) {
		JPanel p = new JPanel();
		p.add(new JLabel("Search Threshold"));
		thresholdText = new JTextField();
		thresholdText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		thresholdText.setText(String.valueOf(peakThreshold));
		p.add(thresholdText);
		return p;
	}

	private Component createPoint(boolean point) {
		JPanel p = new JPanel();
		p.setBorder(new TitledBorder("Fitting Method"));
		pointRadio = new JRadioButton("Point");
		pointRadio.setSelected(point);
		p.add(pointRadio);
		pointRadio.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				areaRadio.setSelected(!pointRadio.isSelected());
				updateMaskedSpan();
			}
			
		});
		areaRadio = new JRadioButton("Area");
		areaRadio.setSelected(!point);
		p.add(areaRadio);
		areaRadio.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				pointRadio.setSelected(!areaRadio.isSelected());
				updateMaskedSpan();
			}
		});
		
		updateMaskedSpan();
		return p;
	}

	private void updateMaskedSpan() {
		if (maskedSpan == null)
			return;
		
		if (pointRadio.isSelected()) {
			maskedSpan.setEnabled(false);
		}
		else {
			maskedSpan.setEnabled(true);
		}
	}

	private Component createFitIntLog(boolean fitInLog) {
		fitInLogCheck = new JCheckBox("Fit in Log");
		fitInLogCheck.setSelected(fitInLog);
		return fitInLogCheck;
	}

	private Component createBpfBandwidth(double bpfBandwidth) {
		JPanel p = new JPanel();
		p.add(new JLabel("Opt. Bandwidth"));
		bpfBandwidthText = new JTextField();
		bpfBandwidthText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		bpfBandwidthText.setText(String.valueOf(bpfBandwidth));
		p.add(bpfBandwidthText);
		bpfBandwidthText.setEnabled(false);
		return p;
	}

	private Component createBpfLevel(double bpfLevel) {
		JPanel p = new JPanel();
		p.add(new JLabel("Opt. Level"));
		bpfLevelText = new JTextField();
		bpfLevelText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		bpfLevelText.setText(String.valueOf(bpfLevel));
		bpfLevelText.setEnabled(false);
		p.add(bpfLevelText);
		return p;
	}

	private Component createNF(String nfcalc) {
		JPanel p = new JPanel();
		p.setLayout(new FlowLayout());
		p.add(new JLabel("NF"));
		nfCombo = new JComboBox();
		nfCombo.addItem("Total");
		nfCombo.addItem("S-ASE");
		nfCombo.setSelectedItem(nfcalc);
		p.add(nfCombo);
		return p;
	}

	private Component createRbw(String rbw, double value) {
		JPanel p = new JPanel();
		p.setLayout(new FlowLayout());
		p.add(new JLabel("RES"));
		rbwCombo = new JComboBox();
		rbwCombo.addItem("Initial");
		rbwCombo.addItem("Measured");
		rbwCombo.addItem("Manual");
		rbwCombo.setSelectedItem(rbw);
		p.add(rbwCombo);
		rbwCombo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				updateRBW();
			}
		});
		rbwText = new JTextField();
		rbwText.setPreferredSize(new Dimension(50, WIDGET_HEIGH));
		rbwText.setText(String.valueOf(value));
		p.add(rbwText);
		updateRBW();
		return p;
	}

	private Component createMethod(String method) {
		JPanel p = new JPanel();
		p.setLayout(new FlowLayout());
		p.add(new JLabel("Method"));
		methodCombo = new JComboBox();
		methodCombo.addItem("IEC");
		methodCombo.addItem("Advanced");
		methodCombo.addItem("SpectDivOn");
		methodCombo.addItem("SpectDivOff");
		methodCombo.addItem("Yokogawa");
		methodCombo.setSelectedItem(method);
		p.add(methodCombo);
		return p;
	}

	private Component createSetButton() {
		JButton b = new JButton("Set");
		b.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				AnalysisProperty prop = new AnalysisProperty();
				if (realSpanRadio.isSelected()) {
					prop.setFittingSpan(Double.valueOf(fittingSpan.getText()));
					prop.setMaskedSpan(Double.valueOf(maskedSpan.getText()));
				}
				else {
					prop.setFittingSpanPoint(Integer.valueOf(fittingSpan.getText()));
					prop.setMaskedSpanPoint(Integer.valueOf(maskedSpan.getText()));
				}
				prop.setFittingVisible(fittingVisible.isSelected());
				prop.setMaskedVisible(maskedVisible.isSelected());
				prop.setFormula(formula.getText());
				prop.setFitInLog(fitInLogCheck.isSelected());
				prop.setMethod((String)methodCombo.getSelectedItem());
				prop.setRbw((String)rbwCombo.getSelectedItem());
				prop.setRbwValue(Double.valueOf(rbwText.getText()));
				prop.setNfcalc((String)nfCombo.getSelectedItem());
				prop.setPinLos(Double.valueOf(pinText.getText()));
				prop.setPoutLoss(Double.valueOf(poutText.getText()));
				prop.setBpfBandwidth(Double.valueOf(bpfBandwidthText.getText()));
				prop.setBpfLevel(Double.valueOf(bpfLevelText.getText()));
				prop.setPoint(pointRadio.isSelected());
				prop.setSliceLevel(Double.valueOf(sliceText.getText()));
				prop.setPeakThreshold(Double.valueOf(thresholdText.getText()));
				prop.setRealSpan(realSpanRadio.isSelected());
				prop.setSpanMethod((String)spanCombo.getSelectedItem());
				prop.setK(Double.valueOf(nfCalText.getText()));
				prop.setLog(checkLogAxis.isSelected());
				prop.setPeak(peakRadio.isSelected());
				prop.setCutLevel(Double.valueOf(cutlevelText.getText()));
				onSetClick(prop);
			}
		});
		return b;
	}

	private Component createMaskedSpan(double d) {
		JPanel p = new JPanel();
		p.setLayout(new FlowLayout());
		p.add(new JLabel("Masked Span"));
		maskedSpan  = new JTextField(String.valueOf(d));
		p.add(maskedSpan);
		maskedSpan.setPreferredSize(new Dimension(60, WIDGET_HEIGH));
		maskedSpan.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {

			}
		});
		p.add(maskedUnit);
		updateMaskedSpan();
		return p;
	}

	private Component createFittingSpan(double d) {
		JPanel p = new JPanel();
		p.setLayout(new FlowLayout());

		p.add(new JLabel("Fitting Span"));
		fittingSpan  = new JTextField(String.valueOf(d));
		p.add(fittingSpan);
		fittingSpan.setPreferredSize(new Dimension(60, WIDGET_HEIGH));
		fittingSpan.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {

			}
		});
		
		p.add(fittingUnit);
		updateFittingSpan();
		return p;
	}

	private Component createFormula(String form) {
		JPanel p = new JPanel();
		p.setLayout(new FlowLayout());
		combo = new JComboBox();
		combo.addItem("Linear");
		combo.addItem("Gauss");
		combo.addItem("2nd");
		combo.addItem("3rd");
		combo.addItem("4th");
		combo.addItem("5th");
		combo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				String sel = (String) ((JComboBox)arg0.getSource()).getSelectedItem();
				if ( sel.equals("Linear")) {
					formula.setText(FORMULA_LINEAR);
					fitInLogCheck.setSelected(false);
				}
				else if ( sel.equals("Gauss")) {
					formula.setText(FORMULA_2ND);
					fitInLogCheck.setSelected(true);
				}
				else if ( sel.equals("2nd")) {
					formula.setText(FORMULA_2ND);
					fitInLogCheck.setSelected(false);
				}
				else if ( sel.equals("3rd")) {
					formula.setText(FORMULA_3RD);
					fitInLogCheck.setSelected(false);
				}
				else if ( sel.equals("4th")) {
					formula.setText(FORMULA_4TH);
					fitInLogCheck.setSelected(false);
				}
				else if ( sel.equals("5th")) {
					formula.setText(FORMULA_5TH);
					fitInLogCheck.setSelected(false);
				}
			}
		});
		formula = new JTextField(form);
		formula.setPreferredSize(new Dimension(300, WIDGET_HEIGH));
		p.add(combo);
		p.add(formula);
		
		if (form.equals(FORMULA_LINEAR)) {
			combo.setSelectedIndex(0);
		}
		else if (form.equals(FORMULA_2ND)) {
			combo.setSelectedIndex(1);
		}
		else if (form.equals(FORMULA_3RD)) {
			combo.setSelectedIndex(3);
		}
		else if (form.equals(FORMULA_4TH)) {
			combo.setSelectedIndex(4);
		}
		else if (form.equals(FORMULA_5TH)) {
			combo.setSelectedIndex(5);
		}

		return p;
	}

	private void updateRBW() {
		if (rbwCombo.getSelectedItem().equals("Manual")) {
			rbwText.setEnabled(true);
		}
		else {
			rbwText.setEnabled(false);
		}
	}
}
